#include "sound.h"
#include "audiomanager.h"
#include "mixchunk.h"

using std::string;
using namespace EPOC;

Sound::Sound(AudioManager *pAudioManager)
{
	m_pAudioManager = pAudioManager;
	SetClassID(kCLASSID_SOUND);

	m_pMixChunk = NULL;

	m_bPlaying = false;
	m_bPause = false;
	m_bDone = true;
	m_bRemoveWhenDone = false;
	m_nCurrentChannel = -1;

	m_nVolume = 0;
	m_nLeftPanning = 0;
	m_nRightPanning = 0;
	m_nDistance = 0;
	m_fPanningRatio = 0.0f;
	m_fDistanceRatio = 0.0f;
	
	
	SetVolume();
	SetPanning();
	SetDistance();
}

Sound::~Sound()
{
	Sound::Cleanup();
}

void Sound::Cleanup()
{
	if(m_pMixChunk)
		m_pMixChunk->Release();

	m_pMixChunk = NULL;
}

bool Sound::Update(float fTimeDelta)
{
	UNREFERENCED_PARAMETER(fTimeDelta);

	if(m_bRemoveWhenDone && IsDone())
		return false;

	return true;
}

void Sound::NotifyChannelDone(int nChannel)
{
	if(m_nCurrentChannel == nChannel)
	{
		m_bDone = true;
		m_bPlaying = false;
		
		SetVolume();
		SetPanning();
		SetDistance();
	}
}

bool Sound::Load(string sFilePath)
{
	//m_sFilePath = sFilePath;
	m_pMixChunk = m_pAudioManager->LoadMixChunkFromFile(sFilePath);//Mix_LoadWAV(m_sFilePath.c_str());

	if(!m_pMixChunk || !m_pMixChunk->GetSDLMixChunk())
	{
		printf("Mix_LoadWAV(%s): %s\n", sFilePath.c_str(), Mix_GetError());
		return false;
	}

	return true;
}

bool Sound::Play(int nLoops)
{
	if(!m_pMixChunk || !m_pMixChunk->GetSDLMixChunk()) return false;

	m_bPlaying = true;
	m_bDone = false;

	m_nCurrentChannel = Mix_PlayChannel(-1, m_pMixChunk->GetSDLMixChunk(), nLoops);
	if(m_nCurrentChannel == -1)
		return false;
	
	Mix_Volume(m_nCurrentChannel, m_nVolume);
	Mix_SetPanning(m_nCurrentChannel, m_nLeftPanning, m_nRightPanning);
	Mix_SetDistance(m_nCurrentChannel, m_nDistance);

	return true;
}


void Sound::Pause()
{
    if(m_bPause == true || m_bPlaying == false || m_nCurrentChannel == -1) return;
	m_bPause = true;

	Mix_Pause(m_nCurrentChannel);
}

void Sound::Resume()
{
	if(m_bPause == false  || m_bPlaying == false || m_nCurrentChannel == -1) return;
	m_bPause = false;

	Mix_Resume(m_nCurrentChannel);
}

void Sound::Stop()
{
	if(m_bPlaying == false  || m_nCurrentChannel == -1) return;
	m_bPlaying = false;
	m_bPause = false;

	Mix_HaltChannel(m_nCurrentChannel);
}

// TODO: check if setting the volume this way is correct
void Sound::SetVolume(int nVolume)
{
	//if(!m_pMixChunk || !m_pMixChunk->GetSDLMixChunk()) return;

	if(nVolume < 0) nVolume = 0;
	else if(nVolume > 100) nVolume = 100;
	
	float fRatio = (float)nVolume / (float)100;

	m_nVolume = (int)(fRatio * (float)MIX_MAX_VOLUME + 0.5f);

	
	if(IsPlaying() || IsPaused())
		Mix_Volume(m_nCurrentChannel, m_nVolume);

	//Mix_VolumeChunk(m_pMixChunk->GetSDLMixChunk(), m_nVolume);
}

int Sound::GetVolume()
{
	//float fRatio = (float)m_nVolume / (float)MIX_MAX_VOLUME;
	//int nVolume = (int)(100.0f * fRatio + 0.5f);

	return m_nVolume;
}

void Sound::SetPanning(float fPanning)
{
	if(fPanning > 1.0f)
		fPanning = 1.0f;
	else if(fPanning < - 1.0f)
		fPanning = -1.0f;

	m_fPanningRatio = fPanning;

	int nValue = (int)((float)255 * m_fPanningRatio);

	m_nRightPanning = 255 + nValue;
	if(m_nRightPanning > 255)
		m_nRightPanning = 255;

	m_nLeftPanning = 255 - nValue;
	if(m_nLeftPanning > 255)
		m_nLeftPanning = 255;

	if(IsPlaying() || IsPaused())
		Mix_SetPanning(m_nCurrentChannel, m_nLeftPanning, m_nRightPanning);
}

float Sound::GetPanning()
{
	return m_fPanningRatio;
}

void Sound::SetDistance(float fDistance)
{
	if(fDistance > 1.0f)
		fDistance = 1.0f;
	else if(fDistance < 0.0f)
		fDistance = 0.0f;

	m_fDistanceRatio = fDistance;
	m_nDistance = (int)((float)255 * m_fDistanceRatio);

	if(IsPlaying() || IsPaused())
		Mix_SetDistance(m_nCurrentChannel, m_nDistance);
}


float Sound::GetDistance()
{
	return m_fDistanceRatio;
}